package com.kaluli.project.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kaluli.project.domain.entity.*;
import com.kaluli.project.domain.repository.*;
import com.kaluli.project.repository.impl.KllZZMessageRepositoryImpl;
import com.kaluli.project.utils.*;
import com.kaluli.project.utils.nanshaxml.EDIXmlBuilder;
import com.kaluli.project.utils.nanshaxml.XmlBuilder;
import com.kaluli.project.utils.nanshaxml.XmlFanli;
import com.kaluli.project.utils.zhuozhi.ZZJsonBuilder;
import com.kaluli.system.annotation.SystemServiceLog;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.apache.log4j.Logger;
import org.dom4j.*;
import org.dom4j.tree.DefaultElement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Configuration
@Transactional
@PropertySource({ "classpath:thridsystem.properties" })
public class KllMainOrderService {

	static Logger log = Logger.getLogger(KllMainOrderService.class.getName());

	private static final String PUSH_AGAIN = "已经存在";

	private static final String GJ_RESULT = "订单数据已存在";

	private static final String START_PUSH = "未初始化完成";

	@Autowired
	private Environment env;

	@Autowired
	private MemoryCache<Privilege> redis;

	@Autowired
	private FtpUtils ftpUtils;

	@Autowired
	private KllMainOrderRepository kllMainOrderRepository;

	@Autowired
	private KllOrderLogisticsService kllOrderLogisticsService;

	@Autowired
	private KllOrderSynApiRepository kllOrderSynApiRepository;

	@Autowired
	private KllMainOrderDetailRepository kllMainOrderDetailRepository;

	@Autowired
	private KllProCustomRepository kllProCustomRepository;
	
	@Autowired
	private KllPurchaserAuthRepository kllPurchaserAuthRepository;
	

	@Autowired
	private KllMqService kllMqService;
	@Autowired
	private RestClient client;

	@Autowired
	private KllZZMessageRepositoryImpl kllZZMessaRepository;

	@Autowired
	private KllMqRepository kllMqRepository;

	@Autowired
	private KllRefundDetailRepository kllRefundDetailRepository;

	@Autowired
	private SendEmailService sendEmailService;

	@Autowired
	private KllOrderVirtualService kllOrderVirtualService;

	@Autowired
	private KllItemSkuRepository kllItemSkuRepository;


	public Long saveMessage(final KllZZMessage message) {
		final Long id = (Long) kllZZMessaRepository.save(message);

		return id;
	}

	public List<KllMainOrder> findAll() {

		return kllMainOrderRepository.findAll();
	}

	public static final String[] MSGCHANNEL = { "ZZ", "GJ", "HG", "ZZ-out", "AlipayHg", "AlipayGj", "Weixin", "EDI" }; // ZZ代表卓志渠道、GJ代表南沙国检渠道、HG代表南沙海关渠道、ZZ-out代表卓志渠道的回调接口

	/**
	 * 订单发送
	 * 
	 * @Scheduled(fixedRate=3000)
	 */

	@SystemServiceLog(description = "发送报文")
	public String[] sendXml(String orderNumber, String channel, String msgId) {
		log.info("发送报文信息:orderNumber=" + orderNumber + "$channel=" + channel + "$msgId=" + msgId);
		KllMainOrder order = kllMainOrderRepository.findByOrderNumber(orderNumber);
		String returnValue[] = new String[3];
		String response = null;
		// String msgIdfix = kllMqService.getMsgId(orderNumber, channel);
		String msgBody = null;
		String id = null;
		try {
			if (channel.equals("ZZ")) {
				msgBody = assmebleyZZJson(order, msgId);
				log.info("ZZ.msgBody=" + msgBody);
				id = msgId;
				ZZresponse res = client.post(env.getProperty("zz.api"), msgBody, ZZresponse.class);
				log.info("notes=" + res.getNotes());
				if (res != null) {
					String notes = res.getNotes();
					String str = order.getIbillingNumber() + PUSH_AGAIN;
					if (StringUtils.isNotBlank(notes) && notes.contains(START_PUSH)) {
						return returnValue;
					}
					if (StringUtils.isNotBlank(notes) && notes.contains(str)) {
						res.setStatus("1");
					}
				}
				response = JSON.toJSONString(res);
				log.info("ZZ.response=" + response);
				returnValue[0] = response;
				returnValue[1] = msgBody;
				createSendLog(order.getOrderNumber(), response, msgBody, channel, "Trade", "ZZ" + msgId);
			}
			if (channel.equals("EDI")) {
				//////////////
				String data = assmbleyEDIXml(order);
				log.info("EDI:request.orderNumber="+order.getOrderNumber());
				String url = env.getProperty("edi.order.create");
				String result = postNr(data,url);
				Document document = DocumentHelper.parseText(result);
				log.info("EDI:response="+document.asXML());
				Element root = document.getRootElement();// 得到根节点
				String success = ((Element) root.selectSingleNode("//result")).getText();
				
				String code = "";
				if (StringUtils.isNotBlank(success) && success.equals("success")) {
					String orderNo = ((Element) root.selectSingleNode("//orderNos//no//orderNo")).getText();
					createResponseLog(order.getOrderNumber(), result, data, channel, "EDI", "EDI"+msgId, true);
					kllOrderSynApiRepository.updateEDIOrderNo(orderNumber,orderNo);
				} else {
					code = ((Element) root.selectSingleNode("//code")).getText();
					createResponseLog(order.getOrderNumber(), result, data, channel, "EDI_ERROR", "EDI"+msgId, false);
				}
			}

			if (channel.equals("AlipayHg")) {
				KllOrderSynApi api = kllOrderSynApiRepository.findByOrderNumber(order.getOrderNumber());
				if(api != null){
					String type = api.getWareType();
					String nrType = env.getProperty("kll.warehouse.nb");
					String nsType = env.getProperty("kll.warehouse.ns");
					String placeHg ="";
					if(nrType.equals(type)){
						placeHg = env.getProperty("alipay.place.nb");
					}else if(nsType.equals(type)){
						placeHg = env.getProperty("alipay.place.ns");
					}
					postAlipay(order, msgId, placeHg, "AlipayHg");
				}
			}

			if (channel.equals("AlipayGj")) {

				String placeGj = env.getProperty("alipay.place.gj");
				postAlipay(order, msgId, placeGj, "AlipayGj");
			}
			if (channel.equals("Weixin")) {
				// 1 是广州 3是宁波  11 是广州总署
				KllOrderSynApi api = kllOrderSynApiRepository.findByOrderNumber(order.getOrderNumber());
				if(api != null){
					String type = api.getWareType();
					String nrType = env.getProperty("kll.warehouse.nb");
					String nsType = env.getProperty("kll.warehouse.ns");
					String customs ="";
					String hgzsUrl ="";
					String hgcode = "";
					if(nrType.equals(type)){
						customs = env.getProperty("weixin.customs.nb");
						hgcode = env.getProperty("alipay.nrhg.code");
						hgzsUrl = getWeixinUrl(order, customs,hgcode);
					}else if(nsType.equals(type)){
						customs = env.getProperty("weixin.customs.ns");
						hgcode = env.getProperty("alipay.rkhg.code");
						hgzsUrl = getWeixinUrl(order, customs,hgcode);
					}
					postWeixin(order, msgId, hgzsUrl,type);
				}
			}
			if (channel.equals("GJ")) {
				// String msgId = env.getProperty("gj.messageprefix") + "_" +
				// System.currentTimeMillis() + "_" + msgIdfix;
				id = env.getProperty("gj.messageprefix") + msgId;
				String[] msgBodyArray = assmbleyGJXml(order, id);
				msgBody = msgBodyArray[1];
				log.info("GJ.file=" + msgBodyArray[0]);
				log.info("GJ.msgBody=" + msgBody);
				response = ftpUtils.upload("", env.getProperty("gj.url"), env.getProperty("gj.username"),
						new Integer(env.getProperty("gj.port")).intValue(), env.getProperty("gj.password"),
						env.getProperty("gj.order.in"), msgBodyArray[0], msgBodyArray[2]);
				log.info("GJ.response=" + response);
				returnValue[0] = msgBodyArray[1];
				returnValue[1] = response;
				returnValue[2] = id;
				createSendLog(order.getOrderNumber(), returnValue[1], returnValue[0], channel, "Trade", returnValue[2]);
			}
			if (channel.equals("HG")) {
				// id = env.getProperty("hg.messagetype.order") + msgId;
				id = UUID.randomUUID().toString().toUpperCase();
				String[] msgBodyArray = assmbleyHGZSXml(order, id);
				msgBody = msgBodyArray[1];
				log.info("HG.file=" + msgBodyArray[0]);
				log.info("HG.msgBody=" + msgBody);
				/*
				 * response = FtpUtils.upload("", env.getProperty("hg.url"),
				 * env.getProperty("hg.username"), new
				 * Integer(env.getProperty("hg.port")).intValue(),
				 * env.getProperty("hg.password"), env.getProperty("hg.upload"),
				 * msgBodyArray[0], msgBodyArray[2]);
				 */
				response = ftpUtils.upload("", env.getProperty("hgzs.ftp.ip"), env.getProperty("hgzs.ftp.username"),
						new Integer(env.getProperty("hgzs.ftp.port")).intValue(), env.getProperty("hgzs.ftp.password"),
						env.getProperty("hgzs.ftp.upload"), msgBodyArray[0], msgBodyArray[2]);
				log.info("HG.response=" + response);
				msgBody = msgBodyArray[1];
				returnValue[0] = msgBodyArray[1];
				returnValue[1] = response;
				returnValue[2] = id;
				createSendLog(order.getOrderNumber(), returnValue[1], returnValue[0], channel, "Trade", returnValue[2]);
			}
		} catch (Exception e) {
			createSendLog(order.getOrderNumber(), e.getMessage(), msgBody, channel, "Trade", id);
			log.error(e);
		}

		// }
		return returnValue;
	}


	public String postNr(String data,String url) throws Exception{
		log.info("params="+data);
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String datetime = sf.format(new Date());
		String secretKey =env.getProperty("edi.secret.key");
		// 签名 base64(md5(报文+密钥+时间))转大写
		String signs = MD5Utils.MD5AndBase64(data + secretKey + datetime).toUpperCase();
		Map<String, String> params = new HashMap<String, String>();
		params.put("data", URLEncoder.encode(data, "UTF-8"));
		params.put("customer", env.getProperty("edi.bus.code"));
		params.put("appkey", env.getProperty("edi.appkey"));
		params.put("secretKey",secretKey);
		params.put("datetime", datetime);
		params.put("sign", URLEncoder.encode(signs, "UTF-8"));
		params.put("serialno", new Date().getTime() + RandomNumber.getRandom());

		String result = HttpUtils.sendPost(url,params);
		return result;
	}


	public void postAlipay(KllMainOrder order, String msgId, String place, String channel) {
		String returnValue[] = new String[3];
		String response = null;
		// String msgIdfix = kllMqService.getMsgId(orderNumber, channel);
		String msgBody = null;
		String id = null;
		try {
			String hgUrl = getAlipayUrl(order, place, channel);
			log.info(channel + ":url=" + hgUrl);
			id = msgId;
			response = client.post(hgUrl);
			log.info(channel + ":response=" + response);
			Document document = DocumentHelper.parseText(response);
			Element root = document.getRootElement();// 得到根节点
			String success = ((Element) root.selectSingleNode("//is_success")).getText();
			String resultCode = "";
			msgBody = "(" + channel + ":url)=" + hgUrl + "||(" + channel + ":response)=" + document.asXML();
			if (StringUtils.isNotBlank(success)) {
				if (success.equals("T")) {
					resultCode = ((Element) root.selectSingleNode("//response/alipay/result_code")).getText();
					if (resultCode.equals("SUCCESS")) {
						response = "{'status':'1'}";
					} else {
						response = "{'status':'0'}";
					}
				} else {
					resultCode = ((Element) root.selectSingleNode("//error")).getText();
					response = "{'status':'0'}";
				}
			} else {
				response = "{'status':'0'}";
			}
			log.info(channel + ":resultCode=" + resultCode);
			returnValue[0] = response;
			returnValue[1] = msgBody;
			createSendLog(order.getOrderNumber(), response, msgBody, channel, "Alipay", "pay" + msgId);
		} catch (Exception e) {
			createSendLog(order.getOrderNumber(), e.getMessage(), msgBody, channel, "Trade", id);
			e.printStackTrace();
		}
	}

	/**
	 * 调用支付宝api
	 * 
	 * @throws NoSuchAlgorithmException
	 *             https://mapi.alipay.com/gateway.do?trade_no=2015051446800462&
	 *             merchant_customs_code=hanguo
	 *             &sign_type=MD5&merchant_customs_name=jwyhanguo_card&sign=
	 *             2118ac8fad6bc1d9e88a6cd017c18d37&amount=2
	 *             &_input_charset=UTF-8&customs_place=HANGZHOU&service=alipay.
	 *             acquire.customs&out_request_no=9193457120563834
	 *             &partner=2088101142878662
	 */
	public String getAlipayUrl(KllMainOrder order, String place, String channel) throws NoSuchAlgorithmException {

		List<KllMq> mqlist = kllMqRepository.findMqOrderNumber(order.getOrderNumber(), channel);
		if (mqlist != null && mqlist.size() > 0) {
			KllMq mq = mqlist.get(0);
			if (mq != null) {
				String msgbody = mq.getMsg_body();
				if (StringUtils.isNotBlank(msgbody)) {
					String[] str = msgbody.split("AlipayGj:response");
					String urls = str[0].trim();
					String url = urls.substring(15, urls.length() - 3);
					return url;
				}

			}
		}
		StringBuffer buffer = new StringBuffer();
		String alipayUrl = env.getProperty("alipay.url");
		buffer.append(alipayUrl);
		String nscode = "";
		if (StringUtils.isNotBlank(channel)) {
			if (channel.equals("AlipayHg")) {
				KllOrderSynApi api = kllOrderSynApiRepository.findByOrderNumber(order.getOrderNumber());
				String nrType = env.getProperty("kll.warehouse.nb");
				String nsType = env.getProperty("kll.warehouse.ns");
				if(api.getWareType().equals(nrType)){
					nscode = env.getProperty("alipay.nrhg.code");
				}else{
					nscode = env.getProperty("alipay.rkhg.code");
				}
				
			} else {
				nscode = env.getProperty("alipay.rkgj.code");
			}
		}
		String nsname = env.getProperty("alipay.ns.name").trim();
		String partner = env.getProperty("alipay.partner.en");
		String amount = order.getTotalPrice().toString();
		String tradeNo = order.getTradeNo();
		if (StringUtils.isBlank(tradeNo)) {
			tradeNo = getTradeNo(partner, order.getIbillingNumber());
			//回写交易流水
			kllMainOrderRepository.updateTradeNo(tradeNo, order.getOrderNumber());
		}
		String ranNumber = RandomNumber.getRandom();
		String date = DateUtils.formatDate(new Date(), "yyyyMMddHHmmssSS");
		String selfCode = date + ranNumber;
		// String selfCode = order.getOrderNumber();
		// 构建签名 签名参数要按顺序排列 32位 MD5
		// _input_charset=UTF-8&amount=2&customs_place=HANGZHOU&merchant_customs_code=hanguo
		// &out_request_no=9193457120563834&partner=2088101142878662&service=alipay.acquire.customs&trade_no=2015051446800462
		String signStr = "_input_charset=UTF-8";
		signStr += "&amount=" + amount;
		signStr += "&customs_place=" + place;
		signStr += "&merchant_customs_code=" + nscode;
		signStr += "&merchant_customs_name=" + nsname;
		signStr += "&out_request_no=" + selfCode;
		signStr += "&partner=" + partner;
		signStr += "&service=alipay.acquire.customs";
		signStr += "&trade_no=" + tradeNo;
		String key = env.getProperty("alipay.key");
		String sign = AlipayMd5Encrypt.md5(signStr + key);
		buffer.append("?" + signStr);
		buffer.append("&sign=" + sign);
		buffer.append("&sign_type=MD5");

		return buffer.toString();
	}

	public String getTradeNo(String partner, String iblliingNo) {
		String tradeNo = "";
		String outTradeNo = DateUtils.formatDate(new Date(), "yyyyMMddHHmmss") + RandomNumber.getRandom();
		StringBuffer buffer = new StringBuffer();
		String key = env.getProperty("alipay.key");
		String alipayUrl = env.getProperty("alipay.url");
		buffer.append(alipayUrl);
		String signStr = "_input_charset=UTF-8";
		signStr += "&out_trade_no=" + iblliingNo;
		signStr += "&partner=" + partner;
		signStr += "&service=single_trade_query";
		String sign = AlipayMd5Encrypt.md5(signStr + key);
		buffer.append("?" + signStr);
		buffer.append("&sign=" + sign);
		buffer.append("&sign_type=MD5");

		String response = null;
		// String msgIdfix = kllMqService.getMsgId(orderNumber, channel);
		String msgBody = null;
		try {
			log.info("TradeNo:url=" + buffer.toString());
			response = client.post(buffer.toString());
			log.info("TradeNo:url:response=" + response);
			Document document = DocumentHelper.parseText(response);
			Element root = document.getRootElement();// 得到根节点
			String success = ((Element) root.selectSingleNode("//is_success")).getText();
			msgBody = document.asXML();
			if (StringUtils.isNotBlank(success)) {
				if (success.equals("T")) {
					tradeNo = ((Element) root.selectSingleNode("//response/trade/trade_no")).getText();
				} else {
					String errorCode = ((Element) root.selectSingleNode("//error")).getText();
					log.info("TradeNo:errorCode=" + errorCode);
					response = "{'errorCode':'" + errorCode + "'}";
				}
			}

			createSendLog(iblliingNo, "{'status':'1'}", msgBody, "TradeNo", "TradeNo", "pay" + outTradeNo);
		} catch (Exception e) {
			createSendLog(iblliingNo, "{'status':'0'}", e.getMessage() + msgBody, "TradeNo", "TradeNo",
					"Excep" + outTradeNo);
			e.printStackTrace();
		}

		return tradeNo;
	}

	public void postWeixin(KllMainOrder order, String msgId, String weixinUrl,String type) {
		String returnValue[] = new String[3];
		String response = null;
		String msgBody = null;
		String id = null;
		try {
			log.info("WeixinUrl:url=" + weixinUrl);
			id = msgId;
			response = client.get(weixinUrl);
			log.info("WeixinUrl:url=" + response);
			Document document = DocumentHelper.parseText(response);
			Element root = document.getRootElement();// 得到根节点
			String success = ((Element) root.selectSingleNode("//retcode")).getText();
			msgBody = "(WeixinUrl:url)=" + weixinUrl + "||(WeixinUrl:response)=" + document.asXML();
			String retmsg = "";
			String nrType = env.getProperty("kll.warehouse.nb");
			String nsType = env.getProperty("kll.warehouse.ns");
			if (StringUtils.isNotBlank(success)) {
				if (success.equals("0")) {
					String status = ((Element) root.selectSingleNode("//state")).getText();
					if(nrType.equals(type)){
						// 4 申报成功
						if (status.equals("1")) {
							response = "{'status':'1'}";
						}
					}else{
						// 4 申报成功
						if (status.equals("4") || status.equals("3")) {
							// if(status.equals("4")){
							response = "{'status':'1'}";
						}
					}
				
					retmsg = ((Element) root.selectSingleNode("//retmsg")).getText();
				} else {
					retmsg = ((Element) root.selectSingleNode("//retmsg")).getText();
					response = "{'status':'0'}";
				}
			} else {
				response = "{'status':'0'}";
			}
			log.info("Weixin:retmsg=" + retmsg);
			returnValue[0] = response;
			returnValue[1] = msgBody;
			createSendLog(order.getOrderNumber(), response, msgBody, "Weixin", "Weixin", "pay" + msgId);
		} catch (Exception e) {
			createSendLog(order.getOrderNumber(), e.getMessage(), msgBody, "Weixin", "error", id);
			e.printStackTrace();
		}
	}

	public String getWeixinUrl(KllMainOrder order, String type,String hgcode) {

		StringBuffer buffer = new StringBuffer();
		String weixinUrl = env.getProperty("weixin.url");
		buffer.append(weixinUrl);

		Map<String, String> paramMap = new HashMap<String, String>();
		paramMap.put("sign_type", "MD5");
		paramMap.put("service_version", "1.0");
		paramMap.put("input_charset", "UTF-8");
		paramMap.put("partner", env.getProperty("weixin.partner"));
		paramMap.put("out_trade_no", order.getIbillingNumber());
		// paramMap.put("out_trade_no", "KLL20160912098163302000012");
		// 1广州 8上海 11 广州电子口岸（总署版）
		paramMap.put("customs", type);
		// 1 新增 2修改（暂只支持郑州综保区，郑州保税物流中心,广州，杭州，宁波） 3 重新推送海关
		paramMap.put("action_type", "1");

		/**
		 * 欧文 补充所有非必要字段参数
		 * 
		 * @author 欧文
		 * @date 2016-9-13
		 */
		// paramMap.put("transaction_id", "");
		// paramMap.put("sub_order_no", "");
		// paramMap.put("fee_type", "CNY");
		// paramMap.put("order_fee","0");
		// paramMap.put("transport_fee","0");
		// paramMap.put("product_fee","0");
		// paramMap.put("duty","0");
		paramMap.put("mch_customs_no", hgcode); // 如果有海关
																				// 设定,必须增加海关备案号
		// paramMap.put("cert_type", "1");
		// paramMap.put("cert_id", "");
		// paramMap.put("name","");
		paramMap.put("business_type", "1");

		String[] keyArray = paramMap.keySet().toArray(new String[0]);
		Arrays.sort(keyArray);

		// 鎷兼帴鏈夊簭鐨勫弬鏁板悕-鍊间覆
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < keyArray.length; i++) {
			if (i == (keyArray.length - 1)) {
				stringBuilder.append(keyArray[i]).append("=").append(paramMap.get(keyArray[i]));
			} else {
				stringBuilder.append(keyArray[i]).append("=").append(paramMap.get(keyArray[i])).append("&");
			}
		}
		String paramUrl = stringBuilder.toString();
		stringBuilder.append("&key=").append(env.getProperty("weixin.key"));

		String sign = AlipayMd5Encrypt.md5(stringBuilder.toString()).toUpperCase();
		buffer.append("?").append(paramUrl);
		buffer.append("&sign=").append(sign);

		return buffer.toString();
	}

	@Transactional(rollbackOn = { RuntimeException.class, Exception.class })
	public Long createSendLog(String order_number, String response, String msgBody, String msgChannel, String msgType,
			String mainOrderId) {

		JSONObject responseObj = null;

		Long sid = null;
		try {
			// if(!msgChannel.equals(MSGCHANNEL[1])){
			responseObj = JSON.parseObject(response);
			// }
			KllMq kllMq = new KllMq();

			kllMq.setOrder_number(order_number);
			// kllMq.setBilling_number(order.getIbillingNumber());
			kllMq.setMsg_body(msgBody);
			kllMq.setMsg_status(1);
			if (msgChannel.equals(MSGCHANNEL[0])) { // 卓志
				kllMq.setMsg_id(mainOrderId);
				if (responseObj.getString("status").equals(env.getProperty("zz.statussuccess"))) { // 如果接口返回信息为成功
					kllMq.setMsg_status(1);

					kllOrderSynApiRepository.updateSynStatus(order_number, msgChannel);
					// 物流写入 清关完成，等待保税仓发货
					kllOrderLogisticsService.updateAbroad("清关完成，等待保税仓发货", order_number);

				} else {
					String orderId = responseObj.getString("orderId");
					if (StringUtils.isNotBlank(orderId) && !orderId.equals("null")) {
						kllOrderSynApiRepository.updateSynStatus(order_number, "ZZ_status");
					}

					kllMq.setMsg_status(0);
				}
				kllMq.setMsg_channel(MSGCHANNEL[0]);
			} else if (msgChannel.equals(MSGCHANNEL[1])) { // 国检
				String msgId = mainOrderId;
				kllMq.setMsg_id(msgId);
				if (responseObj.getString("status").equals("1")) { // 如果接口返回信息为成功

					kllMq.setMsg_status(1);
					kllOrderSynApiRepository.updateSynStatus(order_number, msgChannel);
				} else {
					kllMq.setMsg_status(0);
				}
				kllMq.setMsg_channel(MSGCHANNEL[1]);
			} else if (msgChannel.equals(MSGCHANNEL[2])) {
				String msgId = mainOrderId;
				kllMq.setMsg_id(msgId);
				if (responseObj.getString("status").equals("1")) { // 如果接口返回信息为成功

					kllMq.setMsg_status(1);
					kllOrderSynApiRepository.updateSynStatus(order_number, msgChannel);
				} else {
					kllMq.setMsg_status(0);
				}
				kllMq.setMsg_channel(MSGCHANNEL[2]);
			} else if (msgChannel.equals(MSGCHANNEL[4])) {
				String msgId = mainOrderId;
				kllMq.setMsg_id(msgId);
				if (responseObj.getString("status").equals("1")) { // 如果接口返回信息为成功

					kllMq.setMsg_status(1);
					kllOrderSynApiRepository.updateSynStatus(order_number, msgChannel);
				} else {
					kllMq.setMsg_status(0);
					kllOrderSynApiRepository.updateSynStatus(order_number, "AlipayHg_error");
				}
				kllMq.setMsg_channel(MSGCHANNEL[4]);
			} else if (msgChannel.equals(MSGCHANNEL[5])) {
				String msgId = mainOrderId;
				kllMq.setMsg_id(msgId);
				if (responseObj.getString("status").equals("1")) { // 如果接口返回信息为成功

					kllMq.setMsg_status(1);
					KllOrderSynApi api = kllOrderSynApiRepository.findByOrderNumber(order_number);
					String url = env.getProperty("gj.alipay.url") + api.getIbillingNumber();
					String result = client.post(url);
					if (StringUtils.isNotBlank(result)) {
						if (result.contains(api.getIbillingNumber())) {
							// 有国检支付单
							kllOrderSynApiRepository.updateSynStatus(order_number, msgChannel);
						} else {
							Date sys = DateUtil.beforeFourHourToNowDate();
							if (api.getSendAlipayDate() != null) {

								if (sys.after(api.getSendAlipayDate())) {
									Privilege pri = redis.get(api.getIbillingNumber());
									if (pri == null || StringUtils.isBlank(pri.getCode())) {
										StringBuffer buffer = new StringBuffer();
										buffer.append("一.国检支付单有问题订单列表:\r\n");
										buffer.append(
												"订单号:" + order_number + "=>=>ibilling号:" + api.getIbillingNumber());
										String emails = env.getProperty("nsapi.mail.alipaygj");
										sendEmailService.sendExmail(buffer.toString(), emails);
										Privilege p = new Privilege();
										p.setCode(order_number);
										redis.set(api.getIbillingNumber(), p);

									}

								}
							}
						}

					}
				} else {
					kllMq.setMsg_status(0);
					kllOrderSynApiRepository.updateSynStatus(order_number, "AlipayGj_error");
				}
				kllMq.setMsg_channel(MSGCHANNEL[5]);
			} else if (msgChannel.equals(MSGCHANNEL[6])) {
				String msgId = mainOrderId;
				kllMq.setMsg_id(msgId);
				if (responseObj.getString("status").equals("1")) { // 如果接口返回信息为成功

					kllMq.setMsg_status(1);
					kllOrderSynApiRepository.updateSynStatus(order_number, msgChannel);
				} else {
					kllMq.setMsg_status(0);
					kllOrderSynApiRepository.updateSynStatus(order_number, "Weixin_error");
				}
				kllMq.setMsg_channel(MSGCHANNEL[6]);
			}

			kllMq.setMsg_time(new Timestamp(System.currentTimeMillis()));
			kllMq.setMsg_response(response);
			kllMq.setMsg_type(msgType); // 默认 订单交易 接口
			kllMq.setMsg_audit(0);
			sid = kllMqService.save(kllMq);

		} catch (Exception e) {
			KllMq kllMq = new KllMq();
			kllMq.setOrder_number(order_number);
			// kllMq.setBilling_number(order.getIbillingNumber());
			kllMq.setMsg_body(msgBody);
			kllMq.setMsg_status(-1); // 发送异常
			kllMq.setMsg_channel(msgChannel);
			kllMq.setMsg_time(new Timestamp(System.currentTimeMillis()));
			kllMq.setMsg_response(response + "   Exception:" + e);
			kllMq.setMsg_type("Trade"); // 默认 订单交易 接口
			kllMq.setMsg_audit(0);
			kllMq.setMsg_id(mainOrderId);
			sid = kllMqService.save(kllMq);
			// kllOrderSynApiRepository.updateSynStatus(order.getOrderNumber(),
			// msgChannel);
			log.error(e);
		}
		return sid;
	}

	@Transactional(rollbackOn = { RuntimeException.class, Exception.class })
	public Long createResponseLog(String order_number, String response, String msgBody, String msgChannel,
			String msgType, String mainOrderId, boolean flag) {

		Long sid = null;
		try {
			// }
			KllMq kllMq = new KllMq();

			kllMq.setOrder_number(order_number);
			// kllMq.setBilling_number(order.getIbillingNumber());
			kllMq.setMsg_body(msgBody);
			kllMq.setMsg_status(1);
			kllMq.setMsg_id(mainOrderId);
			if (msgChannel.equals(MSGCHANNEL[7])) {
				
				if (flag) { // 如果接口返回信息为成功
					kllMq.setMsg_status(1);
					kllOrderSynApiRepository.updateSynStatus(order_number, msgChannel);
					
				} else {
					kllOrderSynApiRepository.updateSynStatus(order_number, "EDI_ERROR");
					kllMq.setMsg_status(0);
				}
				
			}
			kllMq.setMsg_channel(msgChannel);
			kllMq.setMsg_time(new Timestamp(System.currentTimeMillis()));
			kllMq.setMsg_response(response);
			kllMq.setMsg_type(msgType); // 默认 订单交易 接口
			kllMq.setMsg_audit(0);
			sid = kllMqService.save(kllMq);

		} catch (Exception e) {
			KllMq kllMq = new KllMq();
			kllMq.setOrder_number(order_number);
			// kllMq.setBilling_number(order.getIbillingNumber());
			kllMq.setMsg_body(msgBody);
			kllMq.setMsg_status(-1); // 发送异常
			kllMq.setMsg_channel(msgChannel);
			kllMq.setMsg_time(new Timestamp(System.currentTimeMillis()));
			kllMq.setMsg_response(response + "   Exception:" + e);
			kllMq.setMsg_type("Trade"); // 默认 订单交易 接口
			kllMq.setMsg_audit(0);
			kllMq.setMsg_id(mainOrderId);
			sid = kllMqService.save(kllMq);
			log.error(e);
		}
		return sid;
	}

	/**
	 * 组装南沙 卓志平台的 订单json数据
	 * 
	 * @param order
	 * @return String
	 */
	private synchronized String assmebleyZZJson(KllMainOrder order, String msgId) {
		ZZJsonBuilder json = ZZJsonBuilder.getInstance();
		ZZOrder zzorder = new ZZOrder();
		zzorder.setOrderId(order.getIbillingNumber());
		zzorder.setOrderDate(order.getOrderTime());
		zzorder.setCustomerId(env.getProperty("zz.customerId"));
		zzorder.setPackingMaterial(""); // 留空
		zzorder.setWarehouseId(""); // 留空
		zzorder.setTpl(env.getProperty("zz.tpl"));
		zzorder.setOrderType(1);
		zzorder.setElectricCode(env.getProperty("zz.electriccode"));
		zzorder.setCbepcomCode(env.getProperty("zz.cbepcomcode"));
		zzorder.setDeliveryCode("");
		zzorder.setNotes(order.getKllMainOrderAttr().getRemark());
		zzorder.setFreightFcy("0");
		zzorder.setFreightFcode("CNY");
		zzorder.setInsuredFee("0");
		zzorder.setTaxFcy("0");
		zzorder.setCustomsType(env.getProperty("hgzs.customstype"));

		Double grossWeight = (double) 0;
		Double netWeight = (double) 0;

		Set<KllMainOrderDetail> details = order.getKllMainOrderDetails();
		ZZOrderDetail zzod = null;
		List<ZZOrderDetail> goodList = new LinkedList<ZZOrderDetail>();
		int index = 1;
		Double totalPrice = order.getTotalPrice();
		int num = order.getNumber();
		Double d = totalPrice / num;
		DecimalFormat df = new DecimalFormat("#.#####");
		Double price = Double.parseDouble(df.format(d));
		for (KllMainOrderDetail detail : details) {
//			KllWareHouse wareHouse = detail.getKllProductSku().getKllWareHouse();
			if (detail.getDepotType().toString().equals(env.getProperty("kll.warehouse.ns"))) {
				zzod = new ZZOrderDetail();
				// 获取海关商品信息
				KllItemCustom custom = kllProCustomRepository.findByCode(detail.getKllProductSku().getCode());
				netWeight += custom.getNetWeight();
				grossWeight += custom.getGrossWeight();
				zzod.setGoodId(custom.getStockNumber());
				zzod.setGnum(index);
				zzod.setAmount(detail.getNumber());
				// zzod.setPrice(detail.getPrice());
				zzod.setPrice(price);
				goodList.add(zzod);
				index++;
			}
		}

		zzorder.setGoodList(goodList);
		zzorder.setNetWeight(netWeight + "");
		zzorder.setGrossWeight(grossWeight + "");
		ZZRecipient recipient = new ZZRecipient();

		String fuisionjson = order.getKllMainOrderAttr().getAddressAttr();
		// JSONArray ja = JSON.parseArray(fuisionjson);
		JSONObject ja = JSON.parseObject(fuisionjson);
		recipient.setName(StringFilters.StringFilter(ja.getString("name")));
		recipient.setAddress(HttpUtils.fixAddress(ja.getString("region")) + ja.getString("street"));
		recipient.setCountry(env.getProperty("zz.country"));
		recipient.setCity(HttpUtils.fixCity(ja.getString("city")));
		recipient.setDistrict(ja.getString("area"));
		recipient.setPostCode(ja.getString("postcode"));
		recipient.setMobilePhone(ja.getString("mobile"));
		recipient.setReceiveNo(ja.getString("identity_number").toUpperCase());
		recipient.setReceiveType(1);
		recipient.setPhone("");
		recipient.setProvince(HttpUtils.fixProvince(ja.getString("province")));
		zzorder.setBuyerName(StringFilters.StringFilter(ja.getString("name")));
		zzorder.setBuyerIdType("1");// 默认1 1-身份证；2-其它
		zzorder.setBuyerIdNumber(ja.getString("identity_number").toUpperCase());
		zzorder.setBuyerTelephone(ja.getString("mobile"));

		zzorder.setRecipient(recipient);

		String jsonStr = json.objToJson(zzorder);

		return jsonStr;
	}
	
	/**
	 * 组装EDI取消订单需要的xml报文
	 * 
	 * @param api
	 * @return String
	 */
	private synchronized String assmbleyCancelEDI(KllOrderSynApi api) {
		// DocumentHelper提供了创建Document对象的方法
		Document document = DocumentHelper.createDocument();
		// 添加节点信息
		Element root = document.addElement(new QName("request"));
		// String guid = UUID.randomUUID().toString().toUpperCase();
		// 这里可以继续添加子节点，也可以指定内容
		root.addElement(new QName("busCode")).addText(env.getProperty("edi.bus.code"));
		root.addElement(new QName("hgCode")).addText(env.getProperty("edi.hg.code"));
		root.addElement(new QName("orderNo")).addText(api.getEdiOrderno());
//		root.addElement(new QName("warehouseCode")).addText(guid);
		String cancelUrl=env.getProperty("edi.cancel.back");
		root.addElement(new QName("notifyUrl")).addText(cancelUrl);
		String no= new Date().getTime()+RandomNumber.getRandom();
		root.addElement(new QName("serialno")).addText(no);
//		root.addElement(new QName("extend")).addText(guid);
		
		return document.asXML();
	}
	
	/**
	 * 取消EDI订单逻辑
	 * @param api
	 */
	public void  cancelEDIOrder(KllOrderSynApi api){
		
		try {
			
			String data = assmbleyCancelEDI(api);
			log.info("EDI:cancel_request="+data);
			StringBuffer bf = new StringBuffer();
			bf.append(data);
			bf.append(env.getProperty("edi.secret.key"));
			String url = env.getProperty("edi.cancel.url");
			String result = postNr(data,url);

			Document document = DocumentHelper.parseText(result);
			log.info("EDI:cancel_response="+document.asXML());
			Element root = document.getRootElement();// 得到根节点
			String success = ((Element) root.selectSingleNode("//result")).getText();
			
			String code = "";
			if (StringUtils.isNotBlank(success) && success.equals("success")) {
				createResponseLog(api.getOrderNumber(), result, url.toString(), "EDI_CANCEL", "EDI_CANCEL", "EDI_CANCEL"+new Date().getTime(), true);
			} else {
				createResponseLog(api.getOrderNumber(), result, url.toString(), "EDI_CANCEL", "EDI_ERROR", "EDI"+new Date().getTime(), false);
			}
		} catch (Exception e) {
			
		}
		
	}

	/**
	 * 组装GJ需要的xml报文
	 * 
	 * @param order
	 * @return String
	 */
	private synchronized String[] assmbleyGJXml(KllMainOrder order, String msgId) {
		XmlBuilder xb = XmlBuilder.getInstance();

		xb.addHeader(XmlBuilder.MESSAGEID, msgId);
		xb.addHeader(XmlBuilder.MESSAGETYPE, env.getProperty("gj.tradeapi"));
		xb.addHeader(XmlBuilder.SENDER, env.getProperty("gj.receiver"));
		xb.addHeader(XmlBuilder.RECEIVER, env.getProperty("gj.sender"));
		xb.addHeader(XmlBuilder.SENDTIME, (new Timestamp(System.currentTimeMillis())).toString());
		xb.addHeader(XmlBuilder.FUNCTIONCODE, "");
		xb.addHeader(XmlBuilder.VERSION, env.getProperty("gj.version"));

		xb.addBody(XmlBuilder.TRADE_SWBEBTRADE, null, false, "ROOT/Body");
		xb.addBody(XmlBuilder.TRADE_RECORD, null, false, "ROOT/Body/swbebtrade");
		xb.addBody(XmlBuilder.TRADE_ENTINSIDENO, order.getIbillingNumber(), true, "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_CIQBCODE, env.getProperty("gj.ciqbcode"), true, "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_CBECOMCODE, env.getProperty("gj.cbecomcode"), true, "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_CBEPCOMCODE, env.getProperty("gj.cbepcomcode"), true,
				"ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_ORDERSTATUS, env.getProperty("gj.neworderstatus"), true,
				"ROOT/Body/swbebtrade/Record");
		String fuisionjson = order.getKllMainOrderAttr().getAddressAttr();
		JSONObject ja = JSON.parseObject(fuisionjson);
		xb.addBody(XmlBuilder.TRADE_RECEIVENAME, StringFilters.StringFilter(ja.getString("name")), true, "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_RECEIVEADDR, ja.getString("region") + ja.getString("street"), true,
				"ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_RECEIVENO, ja.getString("identity_number"), true, "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_RECEIVEPHONE, ja.getString("mobile"), true, "ROOT/Body/swbebtrade/Record");

		xb.addBody(XmlBuilder.TRADE_FCODE, env.getProperty("gj.fcode"), true, "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_EDITCCODE, env.getProperty("gj.editcode"), true, "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_DRDATE, order.getOrderTime(), true, "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_SWBEBTRADEG, null, false, "ROOT/Body/swbebtrade/Record");
		Set<KllMainOrderDetail> details = order.getKllMainOrderDetails();
		// List<ZZOrderDetail> goodList = new LinkedList<ZZOrderDetail>();

		Double totalPrice = 0.0;
		int index = 1;
		for (KllMainOrderDetail o : details) {
			if (o.getDepotType().toString().equals(env.getProperty("kll.warehouse.ns"))) {
				totalPrice += o.getTotalPrice();
				xb.addBody(XmlBuilder.TRADE_RECORD, null, false, "ROOT/Body/swbebtrade/Record/swbebtradeg");
				xb.addBody(XmlBuilder.TRADE_ENTGOODSNO, index, true, "ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				String code = o.getKllProductSku().getCode();
				// 获取海关商品信息
				KllItemCustom custom = kllProCustomRepository.findByCode(code);
				if (custom != null) {
					xb.addBody(XmlBuilder.TRADE_GCODE, custom.getStockNumber(), true,
							"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
					xb.addBody(XmlBuilder.TRADE_HSCODE, custom.getHsCode(), true,
							"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
					xb.addBody(XmlBuilder.TRADE_CIQGOODSNO, custom.getInspectionCode(), true,
							"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				} else {
					xb.addBody(XmlBuilder.TRADE_ENTGOODSNO, o.getGoodsId().toString(), true,
							"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
					xb.addBody(XmlBuilder.TRADE_GCODE, "", true, "ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
					xb.addBody(XmlBuilder.TRADE_HSCODE, "", true, "ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
					xb.addBody(XmlBuilder.TRADE_CIQGOODSNO, "", true, "ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				}
				xb.addBody(XmlBuilder.TRADE_CopGName, o.getKllProduct().getTitle(), true,
						"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				xb.addBody(XmlBuilder.TRADE_SPEC, o.getKllProductSku().getWareSku(), true,
						"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				xb.addBody(XmlBuilder.TRADE_ORIGIN, "", true, "ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				xb.addBody(XmlBuilder.TRADE_QTY, o.getKllProductSku().getWeight(), true,
						"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				xb.addBody(XmlBuilder.TRADE_QTYUNIT, "000", true, "ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				xb.addBody(XmlBuilder.TRADE_DECPRICE, o.getPrice(), true,
						"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				xb.addBody(XmlBuilder.TRADE_DECTOTAL, o.getTotalPrice(), true,
						"ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				xb.addBody(XmlBuilder.TRADE_SELLWEBSITE, "http://www.kaluli.com/product/" + o.getProductId() + ".html",
						true, "ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				xb.addBody(XmlBuilder.TRADE_NOTS, "", true, "ROOT/Body/swbebtrade/Record/swbebtradeg/Record");
				index++;
			}
		}
		// xb.addBody(XmlBuilder.TRADE_FCY, totalPrice.toString(), true,
		// "ROOT/Body/swbebtrade/Record");
		xb.addBody(XmlBuilder.TRADE_FCY, order.getTotalPrice().toString(), true, "ROOT/Body/swbebtrade/Record");
		String localTmp = env.getProperty("gj.local");
		java.util.Date current = new java.util.Date();
		java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");

		List<KllMq> mqs = (List<KllMq>) kllMqService.getByOrderNumber(order.getOrderNumber(), "GJ");

		String fileName = env.getProperty("gj.tradeapi") + "_" + sdf.format(current) + RandomNumber.getRandom();

		File f = new File(localTmp);

		File tmpFtpFile = null;
		String destFileName = null;
		try {
			// destFileName = localTmp + File.separator + fileName + ".xml";
			destFileName = localTmp + "/" + fileName + ".xml";
			tmpFtpFile = new File(destFileName);
			tmpFtpFile.createNewFile();
			if (tmpFtpFile.exists()) {
				// tmpFtpFile.deleteOnExit();
				OutputStreamWriter writerStream = new OutputStreamWriter(new FileOutputStream(tmpFtpFile), "UTF-8");
				BufferedWriter out = new BufferedWriter(writerStream);

				out.write(xb.toString());
				out.close();
			}

		} catch (IOException e) {
			log.error(e);
		}
		String returnValue[] = new String[3];
		returnValue[0] = destFileName;
		returnValue[1] = xb.toString();
		returnValue[2] = fileName + ".xml";
		return returnValue;
	}

	/**
	 * 组装EDI需要的xml报文
	 * 
	 * @param order
	 * @return String
	 */
	private synchronized String assmbleyEDIXml(KllMainOrder order) {
		EDIXmlBuilder xb = EDIXmlBuilder.getInstance();

		xb.addHeader(EDIXmlBuilder.METHOD_TYPE, env.getProperty("edi.method.type"));
		xb.addHeader(EDIXmlBuilder.HG_CODE, env.getProperty("edi.hg.code"));// NBC=宁波海关
		xb.addHeader(EDIXmlBuilder.BUS_CODE, env.getProperty("edi.bus.code"));

		xb.addBody(EDIXmlBuilder.EDI_BODY, null, false, "request/body");
		xb.addBody(EDIXmlBuilder.ORDERSHOP, env.getProperty("edi.order.shop"), true, "request/body/order");
		// xb.addBody(EDIXmlBuilder.OTOCODE, "", true,
		// "request/body/order");//OTO店铺代码
		xb.addBody(EDIXmlBuilder.HGAREA, env.getProperty("edi.hg.area"), true, "request/body/order");// 3105=北仑保税区
		//  TAOBAO=淘宝
		xb.addBody(EDIXmlBuilder.ORDERFROM, env.getProperty("edi.order.from"), true, "request/body/order");
		// 0=不是，1=是
		xb.addBody(EDIXmlBuilder.PACKAGEFLAG, env.getProperty("edi.package.flag"), true, "request/body/order");
		xb.addBody(EDIXmlBuilder.BUSORDERNO, order.getIbillingNumber(), true, "request/body/order");
		String fuisionjson = order.getKllMainOrderAttr().getAddressAttr();
		JSONObject ja = JSON.parseObject(fuisionjson);
		xb.addBody(EDIXmlBuilder.POSTFEE, order.getExpressFee(), true, "request/body/order");// 运费
		xb.addBody(EDIXmlBuilder.INSURANCEFEE, "0", true, "request/body/order");// 保价费
		xb.addBody(EDIXmlBuilder.AMOUNT, order.getTotalPrice(), true, "request/body/order");// 买家实付金额
		xb.addBody(EDIXmlBuilder.BUYERACCOUNT, order.getHupuUid(), true, "request/body/order");
		xb.addBody(EDIXmlBuilder.PHONE, ja.getString("mobile"), true, "request/body/order");
		
		
		String duty = env.getProperty("hg.newpricetaxrate");
		String dutyAll = env.getProperty("hg.pricetaxrate");
		BigDecimal totailPrice = new BigDecimal(order.getTotalPrice());
		BigDecimal expressFee = new BigDecimal(order.getExpressFee());
		BigDecimal couponFee = new BigDecimal(0);
		BigDecimal allPrice = totailPrice.add(couponFee);
		BigDecimal price = allPrice.divide(new BigDecimal(dutyAll),2,BigDecimal.ROUND_HALF_UP);//X
		BigDecimal tax = allPrice.subtract(price).setScale(2, BigDecimal.ROUND_HALF_UP);
		BigDecimal amount = price.subtract(expressFee).setScale(2, BigDecimal.ROUND_HALF_UP);
		
		xb.addBody(EDIXmlBuilder.TAXAMOUNT, tax, true, "request/body/order");// 税额
		xb.addBody(EDIXmlBuilder.TARIFFAMOUNT, "0", true, "request/body/order");// 关税额
		xb.addBody(EDIXmlBuilder.ADDEDVALUETAXAMOUNT, tax, true, "request/body/order");// 增值税额
		xb.addBody(EDIXmlBuilder.CONSUMPTIONDUTYAMOUNT, "0", true, "request/body/order");// 消费税额
		Set<KllMainOrderDetail> details = order.getKllMainOrderDetails();
		// 毛重这里不做处理
		xb.addBody(EDIXmlBuilder.GROSSWEIGHT, "2", true, "request/body/order");
		xb.addBody(EDIXmlBuilder.DISAMOUNT, 0, true,
				"request/body/order");// 优惠金额合计
		xb.addBody(EDIXmlBuilder.DEALDATE,DateUtil.date2Str(order.getOrderTime(), "yyyy-MM-dd HH:mm:ss"), true, "request/body/order");
		xb.addBody(EDIXmlBuilder.REMARK, "", true, "request/body/order");
		
	/*	BigDecimal marketFee = new BigDecimal(order.getMarketingFee());
		BigDecimal margin =marketFee.multiply(new BigDecimal(duty).divide(new BigDecimal(100)));
		xb.addBody(EDIXmlBuilder.TAXAMOUNT, new BigDecimal(order.getDutyFee()).add(margin).setScale(2, BigDecimal.ROUND_HALF_UP), true, "request/body/order");// 税额
		xb.addBody(EDIXmlBuilder.TARIFFAMOUNT, "0", true, "request/body/order");// 关税额
		xb.addBody(EDIXmlBuilder.ADDEDVALUETAXAMOUNT, new BigDecimal(order.getDutyFee()).add(margin).setScale(2, BigDecimal.ROUND_HALF_UP), true, "request/body/order");// 增值税额
		xb.addBody(EDIXmlBuilder.CONSUMPTIONDUTYAMOUNT, "0", true, "request/body/order");// 消费税额
		Set<KllMainOrderDetail> details = order.getKllMainOrderDetails();
		// 毛重这里不做处理
		xb.addBody(EDIXmlBuilder.GROSSWEIGHT, "2", true, "request/body/order");
		BigDecimal market= new BigDecimal(order.getMarketingFee());
		BigDecimal couponFee = new BigDecimal(order.getCouponFee());
		xb.addBody(EDIXmlBuilder.DISAMOUNT, market.add(couponFee).add(margin).setScale(2, BigDecimal.ROUND_HALF_UP), true, "request/body/order");// 优惠金额合计
		xb.addBody(EDIXmlBuilder.DEALDATE,DateUtil.date2Str(order.getOrderTime(), "yyyy-MM-dd HH:mm:ss") , true, "request/body/order");
		xb.addBody(EDIXmlBuilder.REMARK, "", true, "request/body/order");
*/
		/*// PROMOTIONS
		xb.addBody(EDIXmlBuilder.PROMOTIONS, null, false,"request/body/order");
		
		for(KllMainOrderDetail o:details){
			xb.addBody(EDIXmlBuilder.PROMOTION, null, false,"request/body/order/promotions");
			xb.addBody(EDIXmlBuilder.PROAMOUNT, o.getMarketing_fee(), true,"request/body/order/promotions/promotion");
			xb.addBody(EDIXmlBuilder.PROAMOUNT, "0", true,"request/body/order/promotions/promotion");
			
		}*/

		xb.addBody(EDIXmlBuilder.GOODS, null, false, "request/body/order");
		int logistics = 10;
		//计算单价*数量总和
		Double priceAll = new Double(0);
		int count =0;
		for (KllMainOrderDetail o : details) {
			priceAll += o.getPrice()*o.getNumber();
			count +=o.getNumber();
		}
		Double chaPrice = priceAll - amount.doubleValue();


		if(order.getAssociate() == 1){
			List<KllOrderVirtual> vList = kllOrderVirtualService.findOrderVirtual(order.getOrderNumber());
			for(KllOrderVirtual v: vList){
				Double p = (round(v.getPrice()*v.getNumber()/priceAll,2))*chaPrice;
				String code = kllItemSkuRepository.findItemSku(v.getGoodsId()).getGoodsNo();
				xb.addBody(EDIXmlBuilder.DETAIL, null, false, "request/body/order/goods");
				xb.addBody(EDIXmlBuilder.PRODUCTID, code, true,
						"request/body/order/goods/detail");//3105166008N0000001
				xb.addBody(EDIXmlBuilder.QTY, v.getNumber(), true, "request/body/order/goods/detail");
				Double pr = v.getPrice()-round(p/v.getNumber(),2);
				xb.addBody(EDIXmlBuilder.PRICE, pr, true, "request/body/order/goods/detail");
				xb.addBody(EDIXmlBuilder.AMOUNT,pr*v.getNumber(), true, "request/body/order/goods/detail");
			}

		}else {

			for (KllMainOrderDetail o : details) {
				Double p = (round(o.getPrice()*o.getNumber()/priceAll,5))*chaPrice;

				xb.addBody(EDIXmlBuilder.DETAIL, null, false, "request/body/order/goods");
				xb.addBody(EDIXmlBuilder.PRODUCTID, o.getKllProductSku().getGoodsNo(), true,
						"request/body/order/goods/detail");//3105166008N0000001
				xb.addBody(EDIXmlBuilder.QTY, o.getNumber(), true, "request/body/order/goods/detail");
				Double pr = o.getPrice()-round(p/o.getNumber(),2);
				xb.addBody(EDIXmlBuilder.PRICE, pr, true, "request/body/order/goods/detail");
				xb.addBody(EDIXmlBuilder.AMOUNT,pr*o.getNumber(), true, "request/body/order/goods/detail");

			}
		}





		// 0：否（默认），1：是
		xb.addBody(EDIXmlBuilder.ISPAYPUSH, "0", true, "request/body/order");

		xb.addBody(EDIXmlBuilder.PAY, null, false, "request/body/order");
		 xb.addBody(EDIXmlBuilder.PAYTIME, DateUtil.date2Str(order.getPayTime(), "yyyy-MM-dd HH:mm:ss"), true,
		 "request/body/order/pay");
		 xb.addBody(EDIXmlBuilder.PAYMENTNO, order.getTradeNo(), true,
		 "request/body/order/pay");
		 xb.addBody(EDIXmlBuilder.ORDERSEQNO, order.getTradeNo(), true,
		 "request/body/order/pay");
		// ALIPAY TENPAY
		String source = "";
		if (order.getPayType() == 2) {
			source = env.getProperty("edi.pay.tenpay");
		} else {
			source = env.getProperty("edi.pay.alipay");
		}
		 xb.addBody(EDIXmlBuilder.SOURCE, source, true,
		 "request/body/order/pay");
		KllPurchaserAuth auth = kllPurchaserAuthRepository.findByUid(order.getHupuUid());
		xb.addBody(EDIXmlBuilder.IDNUM, auth.getCardNumber(), true, "request/body/order/pay");
		xb.addBody(EDIXmlBuilder.NAME, auth.getPurchaser(), true, "request/body/order/pay");

		xb.addBody(EDIXmlBuilder.LOGISTICS, null, false, "request/body/order");
		
		//江浙用天天，其他区域用韵达 逻辑添加
		String province = ja.getString("province");
		/*
		String logisticsCode="";
		if(HttpUtils.CheckProvince(province)){
			logisticsCode = env.getProperty("edi.logistics.chang");
		}else{
			logisticsCode = env.getProperty("edi.logistics.other");
		}*/
		String logisticsCode = env.getProperty("edi.logistics.other");
		xb.addBody(EDIXmlBuilder.LOGISTICSCODE, logisticsCode, true,
				"request/body/order/logistics");
		xb.addBody(EDIXmlBuilder.CONSIGNEE, StringFilters.StringFilter(ja.getString("name")), true, "request/body/order/logistics");
		xb.addBody(EDIXmlBuilder.PROVINCE, province, true, "request/body/order/logistics");
		xb.addBody(EDIXmlBuilder.CITY, ja.getString("city"), true, "request/body/order/logistics");
		String area =ja.getString("area");
		if(StringUtils.isBlank(area)){
			area = "其他";
		}
		xb.addBody(EDIXmlBuilder.DISTRICT, area, true, "request/body/order/logistics");
		xb.addBody(EDIXmlBuilder.CONSIGNEEADDR, HttpUtils.fixAddress(ja.getString("region")) + ja.getString("street"),
				true, "request/body/order/logistics");
		xb.addBody(EDIXmlBuilder.CONSIGNEETEL, ja.getString("mobile"), true, "request/body/order/logistics");
		xb.addBody(EDIXmlBuilder.MAILNO, ja.getString("postcode"), true, "request/body/order/logistics");
		// xb.addBody(EDIXmlBuilder.GOODSNAME, "1", true,
		// "request/body/order/logistics");
		return xb.toString();
	}

	public double round(double value, int scale) {  
        BigDecimal bd = new BigDecimal(value);  
        bd = bd.setScale(scale, BigDecimal.ROUND_HALF_UP);  
        double d = bd.doubleValue();  
        bd = null;  
        return d;  
    }
	
	public void updateLogistics(String ibillingNumber, String expressNumber) {
		KllMainOrder mainOrder = kllMainOrderRepository.findByIbillingNumber(ibillingNumber);
		if (mainOrder != null) {

			// 物流写入 包裹已出库：广州南沙保税仓
			kllOrderLogisticsService.updateAbroad("包裹已出库：广州南沙保税仓", mainOrder.getOrderNumber());

			// 回写物流单号
			kllOrderLogisticsService.updateExpressNum(expressNumber, mainOrder.getOrderNumber());

		}

	}

	/**
	 * 组装HG需要的xml报文
	 * 
	 * @param order
	 * @return String
	 */
	private synchronized String[] assmbleyHGXml(KllMainOrder order, String msgId) {
		XmlBuilder xb = XmlBuilder.getInstance("HG");

		xb.addHeader(XmlBuilder.MESSAGEID, msgId);
		xb.addHeader(XmlBuilder.MESSAGETYPE, env.getProperty("hg.messagetype.order"));
		xb.addHeader(XmlBuilder.HG_SENDER, env.getProperty("hg.sender"));
		String sendTime = DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
		xb.addHeader(XmlBuilder.SENDTIME, sendTime);
		xb.addHeader(XmlBuilder.VERSION, env.getProperty("hg.version"));
		xb.addBody(XmlBuilder.HG_EORDER, null, false, "Manifest/Declaration");
		xb.addBody(XmlBuilder.HG_ORDERID, order.getIbillingNumber(), true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_IEFLAG, "I", true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_ORDERSTATUS, "S", true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_ENTRECORDNO, env.getProperty("hg.entrecordno"), true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_ENTRECORDNAME, env.getProperty("hg.entrecordname"), true,
				"Manifest/Declaration/EOrder");
		// xb.addBody(XmlBuilder.HG_ORDERNAME, order.getKllMainOrderAttr().,
		// isleaf, parentName)
		String fuisionjson = order.getKllMainOrderAttr().getAddressAttr();
		JSONObject ja = JSON.parseObject(fuisionjson);
		xb.addBody(XmlBuilder.HG_ORDERNAME, StringFilters.StringFilter(ja.getString("name")), true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_ORDERDOCTYPE, "01", true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_ORDERDOCID, ja.getString("identity_number"), true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_ORDERPHONE, ja.getString("mobile"), true, "Manifest/Declaration/EOrder");
		//
		xb.addBody(XmlBuilder.HG_ORDERGOODTOTALCURR, env.getProperty("hg.curr"), true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_FREIGHT, order.getExpressFee(), true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_FREIGHTCURR, env.getProperty("hg.curr"), true, "Manifest/Declaration/EOrder");

		xb.addBody(XmlBuilder.HG_EORDERGOODS, null, false, "Manifest/Declaration");
		// xb.addBody(XmlBuilder.HG_TAX,)、
		Set<KllMainOrderDetail> details = order.getKllMainOrderDetails();
		Double totalPrice = 0.0;
		int index = 1;
		for (KllMainOrderDetail o : details) {
			if (o.getDepotType().toString().equals(env.getProperty("kll.warehouse.ns"))) {
				totalPrice += o.getTotalPrice();
				// 获取海关商品信息
				String code = o.getKllProductSku().getCode();
				KllItemCustom custom = kllProCustomRepository.findByCode(code);
				xb.addBody(XmlBuilder.HG_EORDERGOOD, null, false, "Manifest/Declaration/EOrderGoods");
				xb.addBody(XmlBuilder.HG_GNO, index, true, "Manifest/Declaration/EOrderGoods/EOrderGood");
				/*
				 * xb.addBody(XmlBuilder.HG_GNO, o.getId(), true,
				 * "Manifest/Declaration/EOrderGoods/EOrderGood");
				 */
				xb.addBody(XmlBuilder.HG_CHILDORDERNO, order.getIbillingNumber(), true,
						"Manifest/Declaration/EOrderGoods/EOrderGood");
				xb.addBody(XmlBuilder.HG_STORERECORDNO, env.getProperty("hg.entrecordno"), true,
						"Manifest/Declaration/EOrderGoods/EOrderGood");
				xb.addBody(XmlBuilder.HG_STORERECORDNAME, env.getProperty("hg.entrecordname"), true,
						"Manifest/Declaration/EOrderGoods/EOrderGood");
				xb.addBody(XmlBuilder.HG_CUSTOMSLISTNO, custom.getCustomCode(), true,
						"Manifest/Declaration/EOrderGoods/EOrderGood");
				// xb.addBody(XmlBuilder.HG_CUSTOMSLISTNO,
				// "GDO51451402190000018", true,
				// "Manifest/Declaration/EOrderGoods/EOrderGood");
				xb.addBody(XmlBuilder.HG_DECPRICE, o.getPrice(), true, "Manifest/Declaration/EOrderGoods/EOrderGood");
				xb.addBody(XmlBuilder.HG_UNIT, "007", true, "Manifest/Declaration/EOrderGoods/EOrderGood");
				xb.addBody(XmlBuilder.HG_GQTY, o.getNumber(), true, "Manifest/Declaration/EOrderGoods/EOrderGood");
				xb.addBody(XmlBuilder.HG_DECLTOTAL, o.getTotalPrice(), true,
						"Manifest/Declaration/EOrderGoods/EOrderGood");
				xb.addBody(XmlBuilder.HG_NOTES, "", true, "Manifest/Declaration/EOrderGoods/EOrderGood");
				index++;
			}

		}

		String ruleswitch = env.getProperty("hg.ruleswitch"); // 是否开启海关税收新政策
		Double currentpricelimit = new Double(env.getProperty("hg.currentpricelimit")); // 现有海关税收限额
		Double currentpricetaxrate = new Double(env.getProperty("hg.currentpricetaxrate")); // 现有海关税收税率
		Double newpricelimit = new Double(env.getProperty("hg.newpricelimit")); // 海关新政税收限额
		Double newpricetaxrate = new Double(env.getProperty("hg.newpricetaxrate")); // 海关新政税收税率
		Double newpricetaxoverrate = new Double(env.getProperty("hg.newpricetaxoverrate")); // 海关新增超额税收税率

		Double tax = 0.0;
		totalPrice = order.getTotalPrice();// 由于订单优惠情况
		if (ruleswitch.equals("1")) { // 开启新政
			// totalPrice = totalPrice + order.getExpressFee();

			if (totalPrice < newpricelimit) { // 如果未超出金额限制
				tax = totalPrice * (newpricetaxrate / 100);
				DecimalFormat df = new DecimalFormat("#.####");
				tax = Double.parseDouble(df.format(tax));

			} else {
				/*
				 * Double taxover = (totalPrice - newpricelimit) *
				 * newpricetaxoverrate; // 超出部分按照超额税率计算 tax = (totalPrice -
				 * (totalPrice - newpricelimit)) * newpricetaxrate + taxover; //
				 * 税收＝限额内税收＋超额税收
				 */
				KllMq kllMq = new KllMq();
				kllMq.setOrder_number(order.getOrderNumber());
				kllMq.setMsg_body("报关价格超过2000");
				kllMq.setMsg_status(3); //
				kllMq.setMsg_channel("HG");
				kllMq.setMsg_time(new Timestamp(System.currentTimeMillis()));
				kllMq.setMsg_response("");// 返回
				kllMq.setMsg_type("Trade"); // 默认 订单交易 接口
				kllMq.setMsg_audit(0);
				kllMq.setMsg_id(msgId);
				kllMqService.save(kllMq);
			}
		} else {

			if (totalPrice >= currentpricelimit) {
				tax = totalPrice * (currentpricetaxrate / 100);
				DecimalFormat df = new DecimalFormat("#.####");
				tax = Double.parseDouble(df.format(tax));
			}
		}
		xb.addBody(XmlBuilder.HG_TAX, tax, true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_TAXCURR, env.getProperty("hg.curr"), true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_ORDERGOODTOTAL, totalPrice, true, "Manifest/Declaration/EOrder");
		xb.addBody(XmlBuilder.HG_NOTE, order.getKllMainOrderAttr().getRemark(), true, "Manifest/Declaration/EOrder");
		String date = DateUtils.formatDate(order.getOrderTime(), "yyyy-MM-dd HH:mm:ss");
		xb.addBody(XmlBuilder.HG_ORDERDATE, date, true, "Manifest/Declaration/EOrder");

		String localTmp = env.getProperty("gj.local");
		File f = new File(localTmp);
		String fileName = msgId;

		File tmpFtpFile = null;
		String destFileName = null;
		try {
			// destFileName = localTmp + File.separator + fileName + ".xml";
			destFileName = localTmp + "/" + fileName + ".xml";
			tmpFtpFile = new File(destFileName);
			tmpFtpFile.createNewFile();
			if (tmpFtpFile.exists()) {
				BufferedWriter out = new BufferedWriter(new FileWriter(tmpFtpFile));
				out.write(AESMessageSigner.getInstance().encrypt(xb.toString().getBytes()));
				out.close();
				/*
				 * OutputStreamWriter writerStream = new OutputStreamWriter(new
				 * FileOutputStream(tmpFtpFile), "UTF-8"); BufferedWriter out =
				 * new BufferedWriter(writerStream);
				 * 
				 * out.write(xb.toString()); out.close();
				 */
			}

		} catch (IOException e) {
			log.error(e);
		}

		String returnValue[] = new String[3];
		returnValue[0] = destFileName;
		returnValue[1] = xb.toString();
		returnValue[2] = fileName + ".xml";
		return returnValue;
	}

	/**
	 * 组装HGZS需要的xml报文
	 * 
	 * @param mainOrder
	 * @return String
	 */
	private synchronized String[] assmbleyHGZSXml(KllMainOrder mainOrder, String guid) {
		// DocumentHelper提供了创建Document对象的方法
		Document document = DocumentHelper.createDocument();
		Namespace namespace = new Namespace("ceb", "http://www.chinaport.gov.cn/ceb");
		// 添加节点信息
		Element rootElement = document.addElement(new QName("CEB311Message", namespace));
		// String guid = UUID.randomUUID().toString().toUpperCase();
		rootElement.addAttribute("version", "1.0");
		rootElement.addAttribute("guid", guid);
		rootElement.addAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
		// 这里可以继续添加子节点，也可以指定内容
		Element order = rootElement.addElement(new QName("Order", namespace));

		Element orderHead = order.addElement(new QName("OrderHead", namespace));

		int num = mainOrder.getNumber();
		Double d = mainOrder.getTotalPrice() / num;
		DecimalFormat df = new DecimalFormat("#.#####");
		Double price = Double.parseDouble(df.format(d));
		orderHead.addElement(new QName("guid", namespace)).addText(guid);
		orderHead.addElement(new QName("appType", namespace)).addText("1");// 企业报送类型。1-新增
																			// 2-变更
																			// 3-删除。默认为1。
		orderHead.addElement(new QName("appTime", namespace)).addText(DateUtil.date2Str(new Date(), "yyyyMMddHHmmss"));
		orderHead.addElement(new QName("appStatus", namespace)).addText("2");// 业务状态:1-暂存,2-申报,默认为2。
		orderHead.addElement(new QName("orderType", namespace)).addText("I");// 电子订单类型：I进口
		orderHead.addElement(new QName("orderNo", namespace)).addText(mainOrder.getIbillingNumber());
		orderHead.addElement(new QName("ebpCode", namespace)).addText(env.getProperty("hgzs.code"));
		orderHead.addElement(new QName("ebpName", namespace)).addText(env.getProperty("hgzs.name"));
		orderHead.addElement(new QName("ebcCode", namespace)).addText(env.getProperty("hgzs.code"));
		orderHead.addElement(new QName("ebcName", namespace)).addText(env.getProperty("hgzs.name"));
		orderHead.addElement(new QName("goodsValue", namespace)).addText(df.format(price * num));// 商品实际成交价
		orderHead.addElement(new QName("freight", namespace)).addText("0");// 不包含在商品价格中的运杂费，无则填写"0"。
		orderHead.addElement(new QName("discount", namespace)).addText("0");// 使用积分、虚拟货币、代金券等非现金支付金额，无则填写"0"。
		orderHead.addElement(new QName("taxTotal", namespace)).addText("0");// 企业预先代扣的税款金额，无则填写“0”
		orderHead.addElement(new QName("acturalPaid", namespace)).addText(mainOrder.getTotalPrice() + "");// 实际支付金额
		orderHead.addElement(new QName("currency", namespace)).addText(env.getProperty("hgzs.curr"));
		String userName = "kaluli";
		if (StringUtils.isNotBlank(mainOrder.getHupuUsername())) {
			userName = mainOrder.getHupuUsername();
		}
		String fuisionjson = mainOrder.getKllMainOrderAttr().getAddressAttr();
		JSONObject ja = JSON.parseObject(fuisionjson);
		orderHead.addElement(new QName("buyerRegNo", namespace)).addText(userName);// 订购人的交易平台注册号。
		orderHead.addElement(new QName("buyerName", namespace)).addText(StringFilters.StringFilter(ja.getString("name")));
		orderHead.addElement(new QName("buyerIdType", namespace)).addText("1");// 1-身份证,2-其它。限定为身份证，填写“1”。
		orderHead.addElement(new QName("buyerIdNumber", namespace)).addText(ja.getString("identity_number").toUpperCase());
		// orderHead.addElement(new QName("payCode",
		// namespace)).addText(env.getProperty("hgzs.paycode"));
		// orderHead.addElement(new QName("payName",
		// namespace)).addText(env.getProperty("hgzs.payname"));
		// orderHead.addElement(new QName("payTransactionId",
		// namespace)).addText(mainOrder.getTradeNo());
		// orderHead.addElement(new
		// QName("batchNumbers",namespace)).addText("1");
		orderHead.addElement(new QName("consignee", namespace)).addText(StringFilters.StringFilter(ja.getString("name")));
		orderHead.addElement(new QName("consigneeTelephone", namespace)).addText(ja.getString("mobile"));
		orderHead.addElement(new QName("consigneeAddress", namespace))
				.addText(ja.getString("region") + ja.getString("street"));
		// orderHead.addElement(new
		// QName("consigneeDistrict",namespace)).addText("1");
		orderHead.addElement(new QName("note", namespace)).addText("");

		Set<KllMainOrderDetail> details = mainOrder.getKllMainOrderDetails();
		Double totalPrice = 0.0;
		int index = 1;
		for (KllMainOrderDetail o : details) {
			if (o.getDepotType().toString().equals(env.getProperty("kll.warehouse.ns"))) {
				totalPrice += o.getTotalPrice();
				// 获取海关商品信息
				String code = o.getKllProductSku().getCode();
				String name = o.getKllProduct().getTitle();
				KllItemCustom custom = kllProCustomRepository.findByCode(code);

				Element orderList = order.addElement(new QName("OrderList", namespace));
				if (custom != null) {

					orderList.addElement(new QName("gnum", namespace)).addText(index + "");
					orderList.addElement(new QName("itemNo", namespace)).addText(code);
					orderList.addElement(new QName("itemName", namespace)).addText(name);
					orderList.addElement(new QName("itemDescribe", namespace)).addText(o.getKllProduct().getIntro());
					orderList.addElement(new QName("barCode", namespace)).addText(code);
					orderList.addElement(new QName("unit", namespace)).addText(env.getProperty("hgzs.unit"));
					orderList.addElement(new QName("qty", namespace)).addText(o.getNumber() + "");
					// orderList.addElement(new
					// QName("price",namespace)).addText(o.getPrice()+"");
					orderList.addElement(new QName("price", namespace)).addText(price + "");
					orderList.addElement(new QName("totalPrice", namespace)).addText(df.format(price * o.getNumber()));
					orderList.addElement(new QName("currency", namespace)).addText(env.getProperty("hgzs.curr"));
					orderList.addElement(new QName("country", namespace)).addText(env.getProperty("hgzs.country"));// 美国
					// 502
				}
				orderList.addElement(new QName("note", namespace)).addText("");

				index++;
			}

		}

		String ruleswitch = env.getProperty("hg.ruleswitch"); // 是否开启海关税收新政策
		Double currentpricelimit = new Double(env.getProperty("hg.currentpricelimit")); // 现有海关税收限额
		Double currentpricetaxrate = new Double(env.getProperty("hg.currentpricetaxrate")); // 现有海关税收税率
		Double newpricelimit = new Double(env.getProperty("hg.newpricelimit")); // 海关新政税收限额
		Double newpricetaxrate = new Double(env.getProperty("hg.newpricetaxrate")); // 海关新政税收税率
		Double newpricetaxoverrate = new Double(env.getProperty("hg.newpricetaxoverrate")); // 海关新增超额税收税率

		Double tax = 0.0;
		totalPrice = mainOrder.getTotalPrice();// 由于订单优惠情况
		if (ruleswitch.equals("1")) { // 开启新政
			// totalPrice = totalPrice + order.getExpressFee();

			if (totalPrice < newpricelimit) { // 如果未超出金额限制
				tax = totalPrice * (newpricetaxrate / 100);
				DecimalFormat de = new DecimalFormat("#.####");
				tax = Double.parseDouble(de.format(tax));

			} else {
				/*
				 * Double taxover = (totalPrice - newpricelimit) *
				 * newpricetaxoverrate; // 超出部分按照超额税率计算 tax = (totalPrice -
				 * (totalPrice - newpricelimit)) * newpricetaxrate + taxover; //
				 * 税收＝限额内税收＋超额税收
				 */
				KllMq kllMq = new KllMq();
				kllMq.setOrder_number(mainOrder.getOrderNumber());
				kllMq.setMsg_body("报关价格超过2000");
				kllMq.setMsg_status(3); //
				kllMq.setMsg_channel("HG");
				kllMq.setMsg_time(new Timestamp(System.currentTimeMillis()));
				kllMq.setMsg_response("");// 返回
				kllMq.setMsg_type("Trade"); // 默认 订单交易 接口
				kllMq.setMsg_audit(0);
				kllMq.setMsg_id(guid);
				kllMqService.save(kllMq);
			}
		} else {

			if (totalPrice >= currentpricelimit) {
				tax = totalPrice * (currentpricetaxrate / 100);
				DecimalFormat dec = new DecimalFormat("#.####");
				tax = Double.parseDouble(dec.format(tax));
			}
		}

		Element baseTransfer = rootElement.addElement(new QName("BaseTransfer", namespace));
		baseTransfer.addElement(new QName("copCode", namespace)).addText(env.getProperty("hgzs.code"));
		baseTransfer.addElement(new QName("copName", namespace)).addText(env.getProperty("hgzs.name"));
		baseTransfer.addElement(new QName("dxpMode", namespace)).addText(env.getProperty("hgzs.dxpmode"));
		baseTransfer.addElement(new QName("dxpId", namespace)).addText(env.getProperty("hgzs.dxpid"));
		baseTransfer.addElement(new QName("note", namespace)).addText("");

		String localTmp = env.getProperty("gj.local");
		File f = new File(localTmp);
		String fileName = env.getProperty("hgzs.filename") + "_" + env.getProperty("hgzs.code") + "_"
				+ DateUtil.date2Str(new Date(), "yyyyMMssHHmmss") + RandomNumber.getRandomFive();

		File tmpFtpFile = null;
		String destFileName = null;
		try {
			// destFileName = localTmp + File.separator + fileName + ".xml";
			destFileName = localTmp + "/" + fileName + ".xml";
			tmpFtpFile = new File(destFileName);
			tmpFtpFile.createNewFile();
			if (tmpFtpFile.exists()) {
				/*
				 * BufferedWriter out = new BufferedWriter(new
				 * FileWriter(tmpFtpFile));
				 * out.write(AESMessageSigner.getInstance().encrypt(document.
				 * toString().getBytes())); out.close();
				 */

				OutputStreamWriter writerStream = new OutputStreamWriter(new FileOutputStream(tmpFtpFile), "UTF-8");
				BufferedWriter out = new BufferedWriter(writerStream);

				out.write(document.asXML());
				out.close();
			}

		} catch (IOException e) {
			log.error(e);
		}

		String returnValue[] = new String[3];
		returnValue[0] = destFileName;
		returnValue[1] = document.asXML();
		returnValue[2] = fileName + ".xml";
		return returnValue;
	}

	private String makeNo(List<KllMq> mqs) {
		String no = "001";
		int size = mqs.size();
		if (size > 0 && size < 10) {
			no = "00" + size;
		} else if (size > 9 && size < 100) {
			no = "0" + size;
		} else if (size > 99 && size < 1000) {
			no = size + "";
		} else {
			no = size + "";
		}

		return no;
	}

	/**
	 * 组装海关需要的报文 todo
	 */

	public static void main(String s[]) {
		String ss = "{'name':'\u5f20\u6587\u677e','postcode':'223322','province':'\u6c5f\u897f','city':'\u5357\u660c','area':'\u7ea2\u8c37\u6ee9\u65b0\u533a','mobile':'15800867003','region':'\u6c5f\u897f \u5357\u660c \u7ea2\u8c37\u6ee9\u65b0\u533a','street':'\u8bf7\u95ee\u5230\u6211\u53bb\u6253\u7403\u6253\u7403','identity_number':'320821198802012131'}";
		JSONObject ja = JSON.parseObject(ss);
		System.out.println(ss);
	}

	@Transactional(rollbackOn = { RuntimeException.class, Exception.class })
	public void receiveGjXmlResponse() {
		/**
		 * todo 获取ftp里的xml文件
		 */
		try {
			List<Document> fileIs = ftpUtils.retrieve(env.getProperty("gj.order.out"), env.getProperty("gj.local"), "",
					env.getProperty("gj.username"), env.getProperty("gj.password"), env.getProperty("gj.url"),
					new Integer(env.getProperty("gj.port")).intValue());
			for (Document is : fileIs) {
				Element root = is.getRootElement();// 得到根节点
				Element ec = (Element) root.selectSingleNode("//OrgMessageID");
				String status = ((Element) root.selectSingleNode("//Status")).getText();
				String notes = ((Element) root.selectSingleNode("//Notes")).getText();
				KllMq kllmq = kllMqService.findByMsgId(ec.getText());
				log.info("GjXmlResponse_OrgMessageID=" + ec.getText() + "&&status=" + status);
				if (status.equals("20")) {
					kllmq.setMsg_id(ec.getText());
					kllmq.setMsg_response(is.asXML());
					kllmq.setMsg_status(0);
					kllMqService.updateMq(kllmq);
					kllOrderSynApiRepository.updateNSynGjEnd(kllmq.getOrder_number());

				} else if (status.equals("10")) {
					kllmq.setMsg_id(ec.getText());
					kllmq.setMsg_response(is.asXML());
					kllMqService.updateMq(kllmq);

					kllOrderSynApiRepository.updateNSynGjStatus(kllmq.getOrder_number());
					// 国检订单重复提交的弥补措施
					// :电商企业1500004240的订单号为KLL20170209056122221116707订单数据已存在
					if (StringUtils.isNotBlank(notes) && notes.contains(GJ_RESULT)) {
						kllOrderSynApiRepository.updateNSynGjStatus(kllmq.getOrder_number());
					}
				}
			}
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			log.error(e);
		} catch (Exception e) {
			log.error(e);
		}

	}

	// 海关
	@Transactional(rollbackOn = { RuntimeException.class, Exception.class })
	public void receiveHgXmlResponse() {
		/**
		 * todo 获取ftp里的xml文件
		 */
		try {
			List<Document> fileIs = ftpUtils.retrieveHG(env.getProperty("hgzs.ftp.download"),
					env.getProperty("gj.local"), "", env.getProperty("hgzs.ftp.username"),
					env.getProperty("hgzs.ftp.password"), env.getProperty("hgzs.ftp.ip"),
					new Integer(env.getProperty("hgzs.ftp.port")).intValue());
			for (Document is : fileIs) {
				is.accept(new NameSpaceCleaner());
				Element root = is.getRootElement();// 得到根节点
				// String guid = ((Element)
				// root.selectSingleNode("/CEB312Message/OrderReturn/guid")).getText();
				String guid = root.attributeValue("guid");
				if (StringUtils.isNotBlank(guid)) {

					String orderNo = ((Element) root.selectSingleNode("/CEB312Message/OrderReturn/orderNo")).getText();
					String returnStatus = ((Element) root.selectSingleNode("/CEB312Message/OrderReturn/returnStatus"))
							.getText();
					KllMq kllmq = kllMqService.findByMsgId(guid);
					// 2电子口岸申报中/3发送海关成功/4发送海关失败/100海关退单/120海关入库

					if (kllmq == null) {
						continue;
					}
					// 报关成功
					if (returnStatus.equals("3") || returnStatus.equals("2")) {
						kllmq.setMsg_id(guid);
						kllmq.setMsg_response(is.asXML());
						kllMqService.updateMq(kllmq);
						kllOrderSynApiRepository.updateNSynHgStatus(kllmq.getOrder_number());
					} else {
						kllmq.setMsg_id(guid);
						kllmq.setMsg_response(is.asXML());
						kllmq.setMsg_status(0);
						kllMqService.updateMq(kllmq);
						kllOrderSynApiRepository.updateNSynHgEnd(kllmq.getOrder_number());

					}
					log.info("HgXmlResponse_OldMessageId=" + guid + "&&status=" + returnStatus);
				} else {
					String messageId = ((Element) root.selectSingleNode("/DocRec/Declaration/OrgMessageID")).getText();
					KllMq kllmq = kllMqService.findByMsgId(messageId);
					kllmq.setMsg_id(messageId);
					kllmq.setMsg_response(is.asXML());
					kllmq.setMsg_status(0);
					kllMqService.updateMq(kllmq);
					kllOrderSynApiRepository.updateNSynHgEnd(kllmq.getOrder_number());
					System.out.println("messageid=" + messageId);
				}

			}
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			log.error(e);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error(e);
		}

	}

	public void updateEDBstock(String ibillingNumber) {
		KllMainOrder mainOrder = kllMainOrderRepository.findByIbillingNumber(ibillingNumber);
		if (mainOrder != null) {
			String url = env.getProperty("edb.update.url");
			String str =env.getProperty("edb.update.sign");
			String source = env.getProperty("edb.update.source");
			try {
				String sign = MD5Utils.MD5_32bit(str).toUpperCase();
				StringBuffer bf = new StringBuffer();
				bf.append(url).append("sign="+sign);
				bf.append("&source="+source);
				bf.append("&orderNumber="+mainOrder.getOrderNumber());

				String response = client.post(bf.toString());
				log.info("update.EDB.num="+ibillingNumber+"&&&response="+response);
				JSONObject ja = JSON.parseObject(response);
				// {“status”:1,"msg":}
				// 1为成功，非0失败，错误信息msg
				String status = ja.getString("status");
				KllMq mq = new KllMq();
				mq.setBilling_number(mainOrder.getIbillingNumber());
				mq.setOrder_number(mainOrder.getOrderNumber());
				mq.setMsg_type("EDB");
				mq.setMsg_body(bf.toString());
				mq.setMsg_response(response);
				mq.setMsg_time(new Timestamp(System.currentTimeMillis()));
				mq.setMsg_audit(0);
				if (StringUtils.isNotBlank(status) && "1".equals(status)) {
					mq.setMsg_status(1);
				} else {
					mq.setMsg_status(0);
				}
				kllMqService.save(mq);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchAlgorithmException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}
	

	private static final class NameSpaceCleaner extends VisitorSupport {
		public void visit(Document document) {
			((DefaultElement) document.getRootElement()).setNamespace(Namespace.NO_NAMESPACE);
			document.getRootElement().additionalNamespaces().clear();
		}

		public void visit(Namespace namespace) {
			namespace.detach();
		}

		public void visit(Attribute node) {
			if (node.toString().contains("xmlns") || node.toString().contains("xsi:")) {
				node.detach();
			}
		}

		public void visit(Element node) {
			if (node instanceof DefaultElement) {
				((DefaultElement) node).setNamespace(Namespace.NO_NAMESPACE);
			}
		}
	}

	// 海关
	@Transactional(rollbackOn = { RuntimeException.class, Exception.class })
	public void receiveHgBakXmlResponse() {
		/**
		 * todo 获取ftp里的xml文件
		 */
		try {
			List<Document> fileIs = ftpUtils.retrieveHG(env.getProperty("hg.download"), env.getProperty("gj.local"), "",
					env.getProperty("hg.username"), env.getProperty("hg.password"), env.getProperty("hg.url"),
					new Integer(env.getProperty("hg.port")).intValue());
			for (Document is : fileIs) {
				Element root = is.getRootElement();// 得到根节点
				Element ec = (Element) root.selectSingleNode("/ResponseMessage/ResponseHead/OldMessageId");
				String status = ((Element) root
						.selectSingleNode("/ResponseMessage/ResponseBodyList/ResponseBody/ReturnCode")).getText();
				KllMq kllmq = kllMqService.findByMsgId(ec.getText());
				if (status.equals("A14")) {
					kllmq.setMsg_id(ec.getText());
					kllmq.setMsg_response(is.asXML());
					kllmq.setMsg_status(0);
					kllMqService.updateMq(kllmq);
					kllOrderSynApiRepository.updateNSynHgEnd(kllmq.getOrder_number());

				} else if (status.equals("C01")) {
					kllmq.setMsg_id(ec.getText());
					kllmq.setMsg_response(is.asXML());
					kllMqService.updateMq(kllmq);
					kllOrderSynApiRepository.updateNSynHgStatus(kllmq.getOrder_number());
				}
				log.info("HgXmlResponse_OldMessageId=" + ec.getText() + "&&status=" + status);
			}
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			log.error(e);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error(e);
		}

	}

	public KllMainOrder findKllMainOrderByOrderNumber(String orderNumber) {
		KllMainOrder mainOrder = kllMainOrderRepository.findByOrderNumber(orderNumber);
		return mainOrder;

	}

	public KllMainOrder findKllMainOrderByIbillingNumber(String ibillingNumber) {
		KllMainOrder mainOrder = kllMainOrderRepository.findByIbillingNumber(ibillingNumber);
		return mainOrder;

	}

	public String findKllMainOrderByChannel(String channel_id, Date begin_date, Date end_date, String order_id,
			String code) {
		StringBuilder hql = new StringBuilder("select * from KllMainOrder order where channelId = ?");
		if (begin_date != null && end_date != null) {
			hql.append(" and order.updatedAt >= ? and order.updatedAt <= ?");
		}
		// todo 起止时间必须都存在才可以通过起止时间过滤
		if (StringUtils.isBlank(order_id)) {
			hql.append(" and order.orderNumber = ?");
		}
		List<KllMainOrder> kllMainOrders = kllMainOrderRepository.findHql(hql.toString(), channel_id, begin_date,
				end_date, order_id);
		XmlFanli xmlFanli = new XmlFanli("orders");
		for (KllMainOrder kllMainOrder : kllMainOrders) {
			// xb.addBody(XmlBuilder.HG_TAX, tax, true,
			// "Manifest/Declaration/EOrder");
			// assmbleyFanliXml(kllMainOrder);
			// xmlFanli.addBody(key, value, isleaf, parentName);
		}
		return xmlFanli.toString();
	}

	/**
	 * 取消南沙订单
	 * 
	 * @param orderNumber
	 */
	@Transactional(rollbackOn = { RuntimeException.class, Exception.class })
	public void cancelResult(String orderNumber,String username) {
		// 查询子订单 插入退款记录
		KllMainOrder mainOrder = kllMainOrderRepository.findByOrderNumber(orderNumber);
		KllOrderSynApi api = kllOrderSynApiRepository.findByOrderNumber(orderNumber);
		//
		KllRefundDetail re = new KllRefundDetail();
		re.setOrderId(mainOrder.getId().toString());
		re.setOrderNumber(orderNumber);
		re.setIbillingNumber(mainOrder.getIbillingNumber());
		re.setRefund(mainOrder.getTotalPrice());
		re.setType(0);// 0订单退款 1表示折扣退款
		re.setPayType(mainOrder.getPayType());
		re.setStatus(0);// 0待退款 1退款成功 2取消退款
		//nsapi
		re.setGrantUsername(username);
		re.setCreateTime(new Timestamp(System.currentTimeMillis()));
		re.setUpdateTime(new Timestamp(System.currentTimeMillis()));
		re.setRefundRemark(username+"订单退款");
		kllRefundDetailRepository.save(re);

		// 更新主订单
		kllMainOrderRepository.updateMainRefund(mainOrder.getTotalPrice(), orderNumber);
		// 更新主订单附表
		Double price = mainOrder.getTotalPrice();
		Double fee = mainOrder.getExpressFee();
		kllMainOrderRepository.updateRefund(price - fee, fee, orderNumber);
		// 更新子订单
		kllMainOrderRepository.updateDetailRefund(orderNumber);
		// 更新推送池
		String name = env.getProperty("user.name.ns");
		if(name.equals(username)){
			
			kllOrderSynApiRepository.updateSynByZZ(orderNumber);
		}else{
			kllOrderSynApiRepository.cancelEDIresult(api.getOrderNumber());
		}

	}

}
